package com.lap.component.gateway.service;

import com.lap.component.gateway.service.acl.Permission;
import com.lap.component.gateway.shared.Constant;
import com.lap.component.gateway.shared.GatewayError;
import com.lap.component.gateway.shared.UriConstant;
import com.lap.framework.common.constant.Header;
import com.lap.framework.common.dto.result.Result;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.reactor.circuitbreaker.operator.CircuitBreakerOperator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Slf4j
@RequiredArgsConstructor
@Service
public class PermissionService {

  private final WebClient webClient;
  private final CircuitBreakerRegistry cbRegistry;

  public Mono<Result<Permission>> getPermission(String userId, String userName, String fullName) {
    CircuitBreaker breaker = cbRegistry.circuitBreaker(Constant.FEIGN_CONFIG);
    return webClient
        .get()
        .uri(UriConstant.GET_PERMISSION)
        .header(Header.USER_ID, userId)
        .header(Header.USER_NAME, userName)
        .header(Header.FULL_NAME, fullName)
        .retrieve()
        .bodyToMono(new ParameterizedTypeReference<Result<Permission>>() {})
        .transformDeferred(CircuitBreakerOperator.of(breaker))
        .onErrorResume(e -> fallback(userId, userName, fullName, e));
  }

  public Mono<Result<Permission>> fallback(
      String userId, String userName, String fullName, Throwable e) {
    log.info(
        "Get user by token fallback:userId{},userName:{},fullName:{},message:{}",
        userId,
        userName,
        fullName,
        e.getLocalizedMessage());
    return Mono.just(Result.fail(GatewayError.FALLBACK));
  }
}
